﻿using UnityEngine;
#pragma warning disable 0414

[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
public class RectDirectorUtility : MonoBehaviour
{
    //private void Awake()
    //{
    //    //Mesh mesh = new Mesh();
    //    //this.GetComponent<MeshFilter>().mesh = mesh;
    //    //Build(1.5f, 6f, 0.25f, 4 * Mathf.Deg2Rad, 30 * Mathf.Deg2Rad);
    //    //BuildMeshComponents();
    //    //mesh.vertices = Vertices;
    //    //mesh.triangles = Triangles;
    //    //mesh.uv = UVs;
    //}

    //// Update is called once per frame
    //void Update()
    //{
        
    //}

    //void OnEnable()
    //{


    //}
    //void OnDisable()
    //{
        
    //}
    //void OnDestroy()
    //{
       
    //}

    //Fan data
    private float deltaDegSides = 5 * Mathf.Deg2Rad;
    private float outerRadius;
    private float outerSideRadius;
    private float innerSideRadius;
    private float innerRadius;
    private float lineWidth;
    private float lintWidthUV;
    private float degFan;
    private Vector3[] Vertices;
    private int[] Triangles;
    private Vector2[] UVs;

    float deg360 = 2 * Mathf.PI;
    float deg90 = 0.5f * Mathf.PI;
    float deg180 = Mathf.PI;
    /// <summary>
    /// 创建扇形 注意是弧度值
    /// </summary>
    /// <param name="innerRadius">内圈半径</param>
    /// <param name="outerRadius">外圈半径</param>
    /// <param name="lineWidth">线宽</param>
    /// <param name="deltaDegSides">每一小段的弧度</param>
    /// <param name="degFan">扇形弧度，2*Math.PI 就是圆</param>
    public void Create(float innerRadius, float outerRadius, float lineWidth, float lineWidthUV, float deltaDegSides, float degFan)
    {
        Mesh mesh = new Mesh();
        this.GetComponent<MeshFilter>().mesh = mesh;
        Build(innerRadius, outerRadius, lineWidth, lineWidthUV, deltaDegSides, degFan);
        BuildMeshComponents();
        mesh.vertices = Vertices;
        mesh.triangles = Triangles;
        mesh.uv = UVs;
    }
    const float degMinFan = 30 * Mathf.Deg2Rad;
    const float minRadius = 1;
    public void Build(float innerRadius, float outerRadius, float lineWidth, float lineWidthUV, float deltaDegSides, float degFan, Material meshMatt = null)
    {
        //MeshHelper.CheckMaterial(ref meshMatt);
        name = "ExFanMesh";
        this.deltaDegSides = deltaDegSides;
        this.outerRadius = Mathf.Max(minRadius, outerRadius);
        this.innerSideRadius = Mathf.Max(0, innerRadius);
        this.outerSideRadius = Mathf.Max(innerRadius, this.outerRadius - lineWidth);
        this.innerRadius = Mathf.Min(this.outerSideRadius, innerSideRadius + lineWidth);
        this.lineWidth = lineWidth;
        this.lintWidthUV = lineWidthUV;
        this.degFan = Mathf.Max(degMinFan, degFan);
    }
    public void SetLayer(int layer)
    {
        transform.gameObject.layer = layer;
        foreach (Transform trans in transform)
        {
            trans.gameObject.layer = layer;
        }
    }
    
    void BuildMeshComponents()
    {
        bool isFan = Mathf.Min(degFan, deg360) < deg360;
        bool isCircle = !isFan && innerSideRadius == 0;

        float cenLen = isCircle ? 0.32725f : 1.309f;
        float sideLen = isCircle ? 0.6545f : 2.618f;
        float cirLen = deg360 * outerRadius;
        float degCen = deg360 / (cirLen / cenLen);
        float degSide = deg360 / (cirLen / sideLen);

        if (isCircle)
        {
            float degTiled = Mathf.Clamp(deg90 - 2 * degCen, 0, deg90);
            int cenSides = Mathf.Max(1, Mathf.FloorToInt(degCen / deltaDegSides));
            int tiledSides = Mathf.Max(1, Mathf.FloorToInt(degTiled / deltaDegSides));
            int deg90Sides = (cenSides * 2 + tiledSides);
            int circleSides = deg90Sides * 4;
            int mid = deg90Sides >> 1;

            int sidesLoop = circleSides;
            int verticesCount = sidesLoop * 2 + 1;
            int trianglesCount = circleSides * 9;
            Vertices = new Vector3[verticesCount];
            Triangles = new int[trianglesCount];
            UVs = new Vector2[verticesCount];

            float curAngle = 0;
            int verIndex = 0;
            int triangleIndex = 0;

            int uvIndex = 0;
            int uvCood = 0;

            Vertices[verIndex++] = Vector3.zero;
            UVs[uvIndex++] = new Vector2(0.0f, 0.0f);

            float uidx = 0.0f;
            float uvDelta = 0.3333f / (float)cenSides;
            float angleDelta = degCen / (float)cenSides;

            for (int i = 0; i < sidesLoop; i++)
            {
                if (uvCood == cenSides + tiledSides)
                {
                    uidx = 0.3333f;
                    uvDelta = 0.3333f / (float)cenSides;
                    angleDelta = degCen / (float)cenSides;
                }
                else if (uvCood == deg90Sides)
                {
                    uvCood = 0;
                    uidx = 0.0f;
                    uvDelta = 0.3333f / (float)cenSides;
                    angleDelta = degCen / (float)cenSides;
                }
                else if (uvCood == cenSides)
                {
                    uidx = 0.3333f;
                    uvDelta = 0.6666f / (float)tiledSides;
                    angleDelta = degTiled / (float)tiledSides;
                }

                UVs[uvIndex++] = new Vector2(uidx, 1.0f);
                UVs[uvIndex++] = new Vector2(uidx, this.lintWidthUV);


                if (uvCood < mid)
                    uidx = Mathf.Abs(uidx + uvDelta);
                else
                    uidx = Mathf.Abs(uidx - uvDelta);

                uvCood++;

                Vector3 vcos_sin = new Vector3(Mathf.Cos(curAngle), Mathf.Sin(curAngle));
                Vector3 outerVertPos = vcos_sin * outerRadius;
                Vector3 outSideVertPos = vcos_sin * outerSideRadius;
                curAngle += angleDelta;

                int idx = verIndex;
                Vertices[verIndex++] = outerVertPos;
                Vertices[verIndex++] = outSideVertPos;

                int a = idx;
                int b = idx + 1;
                int c = (verIndex % verticesCount);
                c = c < verIndex ? c + 1 : c;
                int d = (verIndex + 1) % verticesCount;
                d = d < verIndex ? d + 1 : d;

                //CCW
                Triangles[triangleIndex++] = b;
                Triangles[triangleIndex++] = d;
                Triangles[triangleIndex++] = c;
                Triangles[triangleIndex++] = c;
                Triangles[triangleIndex++] = a;
                Triangles[triangleIndex++] = b;

                Triangles[triangleIndex++] = b;
                Triangles[triangleIndex++] = 0;
                Triangles[triangleIndex++] = d;
            }
        }
        else if (!isFan && !isCircle)
        {
            float degTiled = Mathf.Clamp(deg90 - 2 * degCen, 0, deg90);
            int cenSides = Mathf.Max(1, Mathf.FloorToInt(degCen / deltaDegSides));
            int tiledSides = Mathf.Max(1, Mathf.FloorToInt(degTiled / deltaDegSides));
            int deg90Sides = (cenSides * 2 + tiledSides);
            int ringSides = deg90Sides * 4;
            int mid = deg90Sides >> 1;

            int sidesLoop = ringSides;
            int verticesCount = sidesLoop * 4;
            int trianglesCount = ringSides * 6 * 3;
            Vertices = new Vector3[verticesCount];
            Triangles = new int[trianglesCount];
            UVs = new Vector2[verticesCount];

            int verIndex = 0;
            int triangleIndex = 0;

            int uvIndex = 0;
            int uvCood = 0;
            float uidx = 0.0f;
            float uvDelta = 0.3333f / (float)cenSides;
            float angleDelta = degCen / (float)cenSides;

            float curAngle = 0.0f;
            for (int idx = 0; idx < sidesLoop; idx++)
            {
                if (uvCood == cenSides + tiledSides)
                {
                    uidx = 0.3333f;
                    uvDelta = 0.3333f / (float)cenSides;
                    angleDelta = degCen / (float)cenSides;
                }
                else if (uvCood == deg90Sides)
                {
                    uvCood = 0;
                    uidx = 0.0f;
                    uvDelta = 0.3333f / (float)cenSides;
                    angleDelta = degCen / (float)cenSides;
                }
                else if (uvCood == cenSides)
                {
                    uidx = 0.3333f;
                    uvDelta = 0.6666f / (float)tiledSides;
                    angleDelta = degTiled / (float)tiledSides;
                }

                UVs[uvIndex++] = new Vector2(uidx, 1.0f);
                UVs[uvIndex++] = new Vector2(uidx, 0.666f);
                UVs[uvIndex++] = new Vector2(uidx, 0.333f);
                UVs[uvIndex++] = new Vector2(uidx, 0.0f);

                if (uvCood < mid)
                    uidx = Mathf.Abs(uidx + uvDelta);
                else
                    uidx = Mathf.Abs(uidx - uvDelta);

                uvCood++;

                Vector3 vcos_sin = new Vector3(Mathf.Cos(curAngle), Mathf.Sin(curAngle));
                curAngle += angleDelta;

                Vector3 outerVertPos = vcos_sin * outerRadius;
                Vector3 outSideVertPos = vcos_sin * outerSideRadius;
                Vector3 innerVertPos = vcos_sin * innerRadius;
                Vector3 innerSideVertPos = vcos_sin * innerSideRadius;

                int curIdx = verIndex;
                Vertices[verIndex++] = outerVertPos;
                Vertices[verIndex++] = outSideVertPos;
                Vertices[verIndex++] = innerVertPos;
                Vertices[verIndex++] = innerSideVertPos;

                int a = curIdx;
                int b = curIdx + 1;
                int c = verIndex % verticesCount;
                int d = (verIndex + 1) % verticesCount;
                int e = curIdx + 2;
                int f = (verIndex + 2) % verticesCount;
                int g = curIdx + 3;
                int h = (verIndex + 3) % verticesCount;

                //CW
                Triangles[triangleIndex++] = b;
                Triangles[triangleIndex++] = a;
                Triangles[triangleIndex++] = d;
                Triangles[triangleIndex++] = d;
                Triangles[triangleIndex++] = a;
                Triangles[triangleIndex++] = c;

                Triangles[triangleIndex++] = b;
                Triangles[triangleIndex++] = d;
                Triangles[triangleIndex++] = e;
                Triangles[triangleIndex++] = d;
                Triangles[triangleIndex++] = f;
                Triangles[triangleIndex++] = e;

                Triangles[triangleIndex++] = e;
                Triangles[triangleIndex++] = f;
                Triangles[triangleIndex++] = g;
                Triangles[triangleIndex++] = g;
                Triangles[triangleIndex++] = f;
                Triangles[triangleIndex++] = h;
            }
        }
        else
        {
            float degHalf = degFan * 0.5f;
            float degTiled = Mathf.Clamp(degHalf - (degSide + degCen), 0, deg180);

            int outterSides = Mathf.Max(1, Mathf.FloorToInt(degSide / deltaDegSides));
            int cenSides = Mathf.Max(1, Mathf.FloorToInt(degCen / deltaDegSides));
            int tiledSides = Mathf.Max(1, Mathf.FloorToInt(degTiled / deltaDegSides));

            int mid = outterSides + tiledSides + cenSides;
            int fanSides = (mid) << 1;

            int verticesCount = (fanSides + 1) * 4;
            int trianglesCount = fanSides * 6 * 3;
            Vertices = new Vector3[verticesCount];
            Triangles = new int[trianglesCount];
            UVs = new Vector2[verticesCount];

            int verIndex = 0;
            int triangleIndex = 0;

            int uvIndex = 0;

            float uidx = 0.0f;
            float uvDelta = 0.3333f / (float)outterSides;
            float angleDelta = degSide / (float)outterSides;

            float curAngle = degHalf;

            int sidesLoop = fanSides + 1;
            for (int idx = 0; idx < sidesLoop; idx++)
            {
                if (idx == outterSides + tiledSides)
                {
                    uidx = 0.6666f;
                    uvDelta = 0.3333f / (float)cenSides;
                    angleDelta = degCen / (float)cenSides;
                }
                else if (idx == fanSides - outterSides)
                {
                    uidx = 0.3333f;
                    uvDelta = 0.3333f / (float)outterSides;
                    angleDelta = degSide / (float)outterSides;
                }
                else if (/*tiledSides != 0 &&*/
                    (idx == outterSides || idx == (mid + cenSides)))
                {
                    uidx = idx == outterSides ? 0.3333f : 0.6666f;
                    uvDelta = 0.3333f / (float)tiledSides;
                    angleDelta = degTiled / (float)tiledSides;
                }

                UVs[uvIndex++] = new Vector2(uidx, 1.0f);
                UVs[uvIndex++] = new Vector2(uidx, 0.666f);
                UVs[uvIndex++] = new Vector2(uidx, 0.333f);
                UVs[uvIndex++] = new Vector2(uidx, 0.0f);

                if (idx < mid)
                    uidx = Mathf.Abs(uidx + uvDelta);
                else
                    uidx = Mathf.Abs(uidx - uvDelta);

                Vector3 vcos_sin = new Vector3(Mathf.Cos(curAngle), Mathf.Sin(curAngle));
                curAngle -= angleDelta;

                Vector3 outerVertPos = vcos_sin * outerRadius;
                Vector3 outSideVertPos = vcos_sin * outerSideRadius;
                Vector3 innerVertPos = vcos_sin * innerRadius;
                Vector3 innerSideVertPos = vcos_sin * innerSideRadius;

                int curIdx = verIndex;
                Vertices[verIndex++] = outerVertPos;
                Vertices[verIndex++] = outSideVertPos;
                Vertices[verIndex++] = innerVertPos;
                Vertices[verIndex++] = innerSideVertPos;

                if (triangleIndex >= trianglesCount)
                    break;

                int a = curIdx;
                int b = curIdx + 1;
                int c = verIndex;
                int d = (verIndex + 1);
                int e = curIdx + 2;
                int f = (verIndex + 2);
                int g = curIdx + 3;
                int h = (verIndex + 3);
                if (mid > idx)
                {
                    //CW
                    Triangles[triangleIndex++] = b;
                    Triangles[triangleIndex++] = a;
                    Triangles[triangleIndex++] = c;
                    Triangles[triangleIndex++] = c;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = b;

                    Triangles[triangleIndex++] = b;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = e;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = e;

                    Triangles[triangleIndex++] = e;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = g;
                    Triangles[triangleIndex++] = g;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = h;
                }
                else
                {
                    //CW
                    Triangles[triangleIndex++] = b;
                    Triangles[triangleIndex++] = a;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = a;
                    Triangles[triangleIndex++] = c;

                    Triangles[triangleIndex++] = b;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = e;
                    Triangles[triangleIndex++] = d;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = e;

                    Triangles[triangleIndex++] = e;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = g;
                    Triangles[triangleIndex++] = g;
                    Triangles[triangleIndex++] = f;
                    Triangles[triangleIndex++] = h;
                }

            }
        }
    }

}
